package com.sinry.common.log.filters;

import com.sinry.common.log.utils.IpUtils;
import com.sinry.common.log.utils.TraceIdUtil;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.GenericFilterBean;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/**
 * @author linxinlei
 * @project sinry-cloud
 * @description 日志过滤器
 * @date 2022/5/31
 **/
@Order(1)
//@Configuration
@WebFilter(urlPatterns = "/*", filterName = "traceIdFilter")
public class LoggerFilter extends GenericFilterBean {

    @Value("${spring.application.name}")
    public String appName;

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        // traceId初始化
        initTraceId(request);
        // parentId初始化
        initParentId(request);
        // spanId初始化
        initSpanId();
        // IP地址初始化
        initRequestIp(request);
        // 执行后续过滤器
        chain.doFilter(servletRequest, servletResponse);
    }

    /**
     * 初始化spanId
     */
    private void initSpanId() {
        TraceIdUtil.setSpanId(TraceIdUtil.genSpanId());
    }

    /**
     * traceId初始化
     */
    private void initTraceId(HttpServletRequest request) {
        //尝试获取http请求中的traceId
        String traceId = request.getHeader(TraceIdUtil.TRACE_ID);
        //如果当前traceId为空或者为默认traceId，则生成新的traceId
        if (!StringUtils.hasText(traceId) || TraceIdUtil.defaultTraceId(traceId)){
            traceId = TraceIdUtil.genTraceId();
        }
        //设置traceId
        TraceIdUtil.setTraceId(traceId);
    }

    /**
     * 初始化调用方id
     */
    private void initParentId(HttpServletRequest request) {
        TraceIdUtil.setParentId(request.getHeader(TraceIdUtil.PARENT_ID));
    }

    /**
     * 初始化ip地址
     */
    private void initRequestIp(HttpServletRequest request) {
        IpUtils.setLogIp(request);
    }

    @Override
    public void destroy() {
        MDC.clear();
    }
}
